home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
elvis
/
input.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-15
|
6KB
|
308 lines
/* input.c */
/* Author:
* Steve Kirkendall
* 16820 SW Tallac Way
* Beaverton, OR 97006
* kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
*/
/* This file contains the input() function, which implements vi's INPUT mode */
#include "vi.h"
/* This function allows the user to replace an existing (possibly zero-length)
* chunk of text with typed-in text. It returns the MARK of the last character
* that the user typed in.
*/
MARK input(from, to, when)
MARK from; /* where to start inserting text */
MARK to; /* extent of text to delete */
int when; /* either WHEN_VIINP or WHEN_VIREP */
{
char key[2]; /* key char followed by '\0' char */
char *build; /* used in building a newline+indent string */
char *scan; /* used while looking at the indent chars of a line */
MARK m;
#ifdef DEBUG
/* if "from" and "to" are reversed, complain */
if (from > to)
{
msg("ERROR: input(%ld:%d, %ld:%d)",
markline(from), markidx(from),
markline(to), markidx(to));
return MARK_UNSET;
}
#endif
key[1] = 0;
/* if we're replacing text with new text, save the old stuff */
/* (Alas, there is no easy way to save text for replace mode) */
if (from != to)
{
cut(from, to);
}
ChangeText
{
/* if doing a dot command, then reuse the previous text */
if (doingdot)
{
/* delete the text thats there now */
if (from != to)
{
delete(from, to);
}
cutname('.');
cursor = paste(from, FALSE, TRUE) + 1L;
}
else
{
/* if doing a change within the line... */
if (from != to && markline(from) == markline(to))
{
/* mark the end of the text with a "$" */
change(to - 1, to, "$");
}
else
{
/* delete the old text right off */
if (from != to)
{
delete(from, to);
}
to = from;
}
/* handle autoindent of the first line, maybe */
cursor = from;
if (*o_autoindent && markline(cursor) > 1L && markidx(cursor) == 0)
{
/* Only autoindent blank lines. */
pfetch(markline(cursor));
if (plen == 0)
{
/* Okay, we really want to autoindent */
pfetch(markline(cursor) - 1L);
for (scan = ptext, build = tmpblk.c;
*scan == ' ' || *scan == '\t';
)
{
*build++ = *scan++;
}
if (build > tmpblk.c)
{
*build = '\0';
add(cursor, tmpblk.c);
cursor += (build - tmpblk.c);
}
}
}
/* repeatedly add characters from the user */
for (;;)
{
/* Get a character */
redraw(cursor, TRUE);
key[0] = getkey(when);
/* if whitespace & wrapmargin is set & we're
/* past the warpmargin, then change the
/* whitespace character into a newline
*/
if ((*key == ' ' || *key == '\t')
&& *o_wrapmargin != 0)
{
pfetch(markline(cursor));
if (idx2col(cursor, ptext, TRUE) > COLS - (*o_wrapmargin & 0xff))
{
*key = '\n';
}
}
/* process it */
switch (*key)
{
case ctrl('['):
goto BreakBreak;
case ctrl('U'):
if (markline(cursor) == markline(from))
{
cursor == from;
}
else
{
cursor &= ~(BLKSIZE - 1);
}
break;
case ctrl('D'):
case ctrl('T'):
mark[27] = cursor;
cmd_shift(cursor, cursor, *key == ctrl('D') ? CMD_SHIFTL : CMD_SHIFTR, TRUE, "");
if (mark[27])
{
cursor = mark[27];
}
else
{
cursor = movefront(cursor, 0L);
}
break;
case '\b':
if (cursor <= from)
{
beep();
}
else if (markidx(cursor) == 0)
{
cursor -= BLKSIZE;
pfetch(markline(cursor));
cursor += plen;
}
else
{
cursor--;
}
break;
case ctrl('W'):
m = movebword(cursor, 1L);
if (markline(m) == markline(cursor) && m >= from)
{
cursor = m;
if (from > cursor)
{
from = cursor;
}
}
else
{
beep();
}
break;
case '\n':
case '\r':
build = tmpblk.c;
*build++ = '\n';
if (*o_autoindent)
{
pfetch(markline(cursor));
for (scan = ptext; *scan == ' ' || *scan == '\t'; )
{
*build++ = *scan++;
}
}
*build = 0;
if (cursor >= to && when != WHEN_VIREP)
{
add(cursor, tmpblk.c);
}
else
{
change(cursor, to, tmpblk.c);
}
redraw(cursor, TRUE);
to = cursor = (cursor & ~(BLKSIZE - 1))
+ BLKSIZE
+ (int)(build - tmpblk.c) - 1;
break;
case ctrl('A'):
if (cursor < to)
{
delete(cursor, to);
}
cutname('.');
to = cursor = paste(cursor, FALSE, TRUE) + 1L;
break;
case ctrl('V'):
if (cursor >= to && when != WHEN_VIREP)
{
add(cursor, "^");
}
else
{
change(cursor, to, "^");
}
redraw(cursor, TRUE);
*key = getkey(0);
if (*key == '\n')
{
/* '\n' too hard to handle */
*key = '\r';
}
change(cursor, cursor + 1, key);
cursor++;
if (cursor > to)
{
to = cursor;
}
break;
case ctrl('L'):
case ctrl('R'):
redraw(MARK_UNSET, FALSE);
break;
default:
if (cursor >= to && when != WHEN_VIREP)
{
add(cursor, key);
cursor++;
to = cursor;
}
else
{
pfetch(markline(cursor));
if (markidx(cursor) == plen)
{
add(cursor, key);
}
else
{
change(cursor, cursor + 1, key);
}
cursor++;
}
} /* end switch(*key) */
} /* end for(;;) */
BreakBreak:;
/* delete any excess characters */
if (cursor < to)
{
delete(cursor, to);
}
} /* end if doingdot else */
} /* end ChangeText */
/* put the new text into a cut buffer for possible reuse */
if (!doingdot)
{
blksync();
cutname('.');
cut(from, cursor);
}
/* move to last char that we inputted, unless it was newline */
if (markidx(cursor) != 0)
{
cursor--;
}
rptlines = 0L;
return cursor;
}